package com.dinghui.pay.controller.alipay;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.dinghui.pay.common.ResponseResult;
import com.dinghui.pay.pojo.TbOrder;
import com.dinghui.pay.pojo.TbUser;
import com.dinghui.pay.pojo.param.AlipayLoginParam;
import com.dinghui.pay.pojo.param.PayOrderParam;
import com.dinghui.pay.pojo.param.UpdateOrderStatusParam;
import com.dinghui.pay.service.OrderService;
import com.dinghui.pay.service.UserService;
import com.dinghui.pay.utils.JwtUtils;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author TRT
 * @desc 小程序支付  开通支付宝沙箱环境https://openhome.alipay.com/platform/sandboxMini.htm
 *  支付宝沙箱APP https://sandbox.alipaydev.com/user/downloadApp.htm
 *  支付宝小程序开发工具：https://render.alipay.com/p/f/fd-jwq8nu2a/pages/home/index.html
 * @date 2021年06月04日 9:23
 */
// 支付宝业务接口
@RestController
@RequestMapping("/api/alipay")
public class AppletController {

    /**
     * 商户平台和支付宝服务器之间使用的非对称加密，需要生成公钥、私钥，其中公钥上传给支付宝服务器，这样商户平台上传数据的时候用私钥加密
     * 支付宝服务器收到数据后用公钥解密；反过来，支付宝向商户平台发送数据的时候，用公钥加密，商户平台接收到数据用私钥解密
     */

    @Value("${alipay.microApp.app-id}")
    private String microApp_appId;

    @Value("${alipay.microApp.public-key}")
    private String microApp_publicKey;

    @Value("${alipay.microApp.private-key}")
    private String microApp_privateKey;

    @Value("${alipay.microApp.gateway}")
    private String gateway;

    @Autowired
    private UserService userService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private OrderService orderService;

    /**
     * 登录
     * @param param
     * @return
     */
    @PostMapping("/login")
    public ResponseResult login(@RequestBody AlipayLoginParam param) {
        // 用户授权 https://opendocs.alipay.com/open/289/105656      新：https://opendocs.alipay.com/open/284/106000
        AlipayClient client = new DefaultAlipayClient(gateway, microApp_appId,
                microApp_privateKey, "json", "UTF-8", microApp_publicKey, "RSA2");
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(param.getAuthCode());
        try {
            AlipaySystemOauthTokenResponse response = client.execute(request);
            if (response.isSuccess()) {
                String userId = response.getUserId();
                TbUser user = new TbUser();
                user.setOpenId(userId);
                int count = userService.getCount(user);
                if (count == 0) {
                    user.setNickname(param.getNickname());
                    user.setPhoto(param.getPhoto());
                    user.setType(2);
                    user.setCreateTime(new Date());
                    userService.save(user);
                }
                user = new TbUser();
                user.setOpenId(userId);
                user = userService.getOne(user);
                long id = user.getUserId();

                //生成token
                String token = jwtUtils.generateToken(id);
                Map<String, Object> result = new HashMap<>();
                result.put("token", token);
                result.put("expire", jwtUtils.getExpire());

                return ResponseResult.success(result);
            } else {
                return ResponseResult.error("登陆授权失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("登陆授权失败");
        }
    }


    /**
     * 小程序付款
     */
    @PostMapping("/microAppPayOrder")
    public ResponseResult microAppPayOrder(@RequestBody PayOrderParam param, @RequestHeader HashMap header) {
        String token = header.get("token").toString();
        Long userId = Long.parseLong(jwtUtils.getClaimByToken(token).getSubject());
        int orderId = param.getOrderId();
        TbUser user = new TbUser();
        user.setUserId(userId);
        long count = userService.getCount(user);
        //判断用户是否存在
        if (count == 0) {
            return ResponseResult.error("用户不存在");
        }
        //获取用户账号的openid字符串
        String openId = userService.getOne(user).getOpenId();

        //判断用户是否拥有这个订单，并且订单是未支付状态
        TbOrder order = new TbOrder();
        order.setUserId(userId.intValue());
        order.setId(orderId);
        order.setStatus(1);
        count = orderService.getCount(order);
        if (count == 0) {
            return ResponseResult.error("不是有效的订单");
        }

        // todo 验证购物券是否有效
        // todo 验证团购活动是否有效

        //查询订单详情信息
        order = new TbOrder();
        order.setId(orderId);
        order = orderService.getOne(order); //订单对象
        String amount = order.getAmount() + ""; //订单金额

        try {
            AlipayClient client = new DefaultAlipayClient(gateway, microApp_appId, microApp_privateKey, "json", "UTF-8", microApp_publicKey, "RSA2");
            // AlipayClient 对象用来连接支付宝平台，只有通过这个独享才能创建支付订单  小程序支付介绍文档：https://opendocs.alipay.com/mini/00arkf
            // 创建支付订单提交的参数 https://opendocs.alipay.com/apis/api_1/alipay.trade.create
            /**
             * out_trade_no：商户订单ID
             * total_amount：交易金额
             * subject： 订单备注
             * buyer_id： user_id
             * notify_url: 接收通知地址
             */
            AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + order.getCode() + "\"," +
                    "\"total_amount\":" + amount + "," +
                    "\"subject\":\"订单备注\"," +
                    "\"buyer_id\":\"" + openId + "\"," +
                    "\"notify_url\":\"http://www.demo.com/test\"" +
                    "}");
            AlipayTradeCreateResponse response = client.execute(request);
            if (response.isSuccess()) {
                String prepayId = response.getTradeNo();
                //更新本地商品订单信息，但是不更新商品订单状态
                order.setPrepayId(prepayId); //保存支付订单ID
                order.setPaymentType(2);
                order.setPaymentType(1); //支付类型
                orderService.update(order);
                return ResponseResult.success("prepayId", prepayId);
            } else {
                return ResponseResult.error("支付订单创建失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("支付宝支付模块故障");
        }
    }

    // 7-5、7-7、7-8


    /**
     * 支付宝付款通知中的数据
     * out_trade_no：商户订单ID
     * trade_no: 支付订单ID
     * trade_status: 交易状态
     */
    // 接收消息通知
    @RequestMapping("/recieveMicroMessage")
    public void recieveMicroMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.setCharacterEncoding("utf-8");
        String tradeNo = request.getParameter("trade_no");
        String code = request.getParameter("out_trade_no");
        String tradeStatus = request.getParameter("trade_status");

        if ("TRADE_FINISHED".equals(tradeStatus) || "TRADE_SUCCESS".equals(tradeStatus)) {
            TbOrder order = new TbOrder();
            order.setCode(code); // 查询条件
            order.setStatus(2);  // 更新字段
            order.setPaymentType(2); // 更新字段
            orderService.updateOrderStatus(order);
        }
        response.setCharacterEncoding("utf-8");
        Writer writer = response.getWriter();
        writer.write("success");
        writer.close();
    }

    /**
     * 查询支付订单状态
     * 的参数 https://opendocs.alipay.com/apis/api_1/alipay.trade.query
     * out_trade_no：商户订单ID
     * trade_no: 支付订单ID
     * query_options: 查询参数
     */
    // 更新商品订单状态 （主动查询支付结果）
    @PostMapping("/updateOrderStatus")
    public ResponseResult updateOrderStatus(@RequestBody UpdateOrderStatusParam param, @RequestHeader HashMap header) {
        String token = header.get("token").toString();
        int userId = Integer.parseInt(jwtUtils.getClaimByToken(token).getSubject());
        int orderId = param.getOrderId();
        TbOrder order = new TbOrder();
        order.setUserId(userId);
        order.setId(orderId);
        int count = orderService.getCount(order);
        if (count == 0) {
            return ResponseResult.error("用户与订单不匹配");
        }
        order = orderService.getOne(order);
        String code = order.getCode();

        try {
            AlipayClient client = new DefaultAlipayClient(
                    gateway,
                    microApp_appId,
                    microApp_privateKey,
                    "json",
                    "UTF-8",
                    microApp_publicKey,
                    "RSA2"
            );
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + code + "\"," +
                    "      \"query_options\":[" +
                    "        \"TRADE_SETTLE_INFO\"" +
                    "      ]" +
                    "  }");
            AlipayTradeQueryResponse response = client.execute(request);
            if (response.isSuccess()) {
                String tradeStatus = response.getTradeStatus();
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    TbOrder tbOrder = new TbOrder();
                    tbOrder.setCode(code); // 查询条件
                    tbOrder.setStatus(2); // 修改值
                    tbOrder.setPaymentType(1); // 修改值
                    orderService.updateOrderStatus(order);
                    return ResponseResult.success("订单状态已修改");
                } else {
                    return ResponseResult.success("订单状态未修改");
                }
            }
            return ResponseResult.success("订单状态未修改");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("查询支付订单失败");
        }
    }



}
